#ifndef KNOWHERE_ASCEND_EXCEPTION
#define KNOWHERE_ASCEND_EXCEPTION

#include <exception>
#include <string>
#include <sstream>
#include <securec.h>

namespace knowhere {
namespace ascend {
class AscendException : public std::exception {
public:
    explicit AscendException(const std::string& msg): msg(msg) {}

    AscendException(const std::string& msg,
                    const char* funcName,
                    const char* file,
                    int line)
    {
        const int msgLen = 1024;
        const int scaleSize = 2;
        int size = msgLen;
        this->msg.resize(size, '\0');
        while (snprintf_s(&this->msg[0], this->msg.size(), this->msg.size(), "Error in %s at %s:%d: %s",
            funcName, file, line, msg.c_str()) < 0) {
            size = size * scaleSize;
            this->msg.resize(size, '\0');
        }
    }

    ~AscendException() = default;

    const char* what() const noexcept override
    {
        return msg.c_str();
    }

private:
    std::string msg;
};
} // namespace ascend
}

#define KNOWHERE_ASCEND_THROW_MSG(MSG)                                                                \
    do {                                                                                          \
        throw knowhere::ascend::AscendException(MSG, __PRETTY_FUNCTION__, __FILE__, __LINE__);        \
    } while (false)

#define KNOWHERE_ASCEND_THROW_FMT(FMT, ...)                                                           \
    do {                                                                                          \
        int size = 1024;                                                                          \
        std::string __s(size, '\0');                                                              \
        while (snprintf_s(&__s[0], __s.size(), __s.size(), FMT, __VA_ARGS__) < 0) {               \
            size = size * 2;                                                                      \
            __s.resize(size, '\0');                                                               \
        }                                                                                         \
        throw knowhere::ascend::AscendException(__s, __PRETTY_FUNCTION__, __FILE__, __LINE__);        \
    } while (false)

#endif